package com.cruise.game.service.impl.user;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cruise.game.common.api.ApiException;
import com.cruise.game.mapper.TransactionMapper;
import com.cruise.game.mapper.UserMapper;
import com.cruise.game.mapper.WithdrawalApplicationMapper;
import com.cruise.game.model.entity.Transaction;
import com.cruise.game.model.entity.User;
import com.cruise.game.model.entity.WithdrawalApplication;
import com.cruise.game.model.param.user.RechargeParam;
import com.cruise.game.model.param.user.WithdrawParam;
import com.cruise.game.model.vo.common.PageResult;
import com.cruise.game.model.vo.user.TransactionVO;
import com.cruise.game.model.vo.user.WithdrawalVO;
import com.cruise.game.service.user.UserTransactionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户交易服务实现
 *
 * @author cruise
 * @date 2025-02-28
 */
@Slf4j
@Service
public class UserTransactionServiceImpl implements UserTransactionService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private TransactionMapper transactionMapper;

    @Resource
    private WithdrawalApplicationMapper withdrawalApplicationMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> recharge(Long userId, RechargeParam param) {
        // 验证充值金额
        if (param.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new ApiException("充值金额必须大于0");
        }

        // 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 创建交易记录
        Transaction transaction = new Transaction();
        transaction.setUserId(userId);
        transaction.setAmount(param.getAmount());
        transaction.setType("recharge");
        transaction.setStatus("pending");
        transaction.setCreatedAt(LocalDateTime.now());
        transaction.setUpdatedAt(LocalDateTime.now());

        transactionMapper.insert(transaction);

        // 这里简化处理，实际项目中应该对接支付网关
        // 模拟支付成功，更新交易状态
        transaction.setStatus("completed");
        transactionMapper.updateById(transaction);

        // 更新用户余额
        userMapper.updateBalance(userId, param.getAmount());

        // 返回支付信息
        Map<String, Object> result = new HashMap<>();
        Map<String, Object> paymentInfo = new HashMap<>();
        paymentInfo.put("appId", "wx123456789");
        paymentInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
        paymentInfo.put("nonceStr", "randomString");
        paymentInfo.put("package", "prepay_id=wx123456789");
        paymentInfo.put("signType", "MD5");
        paymentInfo.put("paySign", "signed_data");

        result.put("paymentInfo", paymentInfo);
        result.put("transactionId", transaction.getId());

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long withdraw(Long userId, WithdrawParam param) {
        // 验证提现金额
        if (param.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new ApiException("提现金额必须大于0");
        }

        // 查询用户信息
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new ApiException("用户不存在");
        }

        // 验证余额是否足够
        if (user.getBalance().compareTo(param.getAmount()) < 0) {
            throw new ApiException("余额不足");
        }

        // 扣减用户余额
        if (userMapper.deductBalance(userId, param.getAmount()) <= 0) {
            throw new ApiException("余额扣减失败，请重试");
        }

        // 创建提现申请
        WithdrawalApplication withdrawal = new WithdrawalApplication();
        withdrawal.setUserId(userId);
        withdrawal.setAmount(param.getAmount());
        withdrawal.setStatus("pending");
        withdrawal.setRemark(param.getRemark());
        withdrawal.setCreatedAt(LocalDateTime.now());
        withdrawal.setUpdatedAt(LocalDateTime.now());

        withdrawalApplicationMapper.insert(withdrawal);

        return withdrawal.getId();
    }

    @Override
    public PageResult<TransactionVO> getTransactionList(Long userId, String type, Integer page, Integer pageSize) {
        // 计算偏移量
        int offset = (page - 1) * pageSize;

        // 使用自定义查询方法，避免双LIMIT问题
        List<Transaction> transactions = transactionMapper.getUserTransactions(userId, type, offset, pageSize);

        // 转换为VO
        List<TransactionVO> transactionVOs = new ArrayList<>();
        for (Transaction transaction : transactions) {
            TransactionVO vo = new TransactionVO();
            BeanUtils.copyProperties(transaction, vo);
            transactionVOs.add(vo);
        }

        // 使用自定义方法计算总记录数
        Long total = transactionMapper.countUserTransactions(userId, type);

        // 构建分页结果
        return PageResult.of(transactionVOs, total, page, pageSize);
    }

    @Override
    public PageResult<WithdrawalVO> getWithdrawalList(Long userId, String status, Integer page, Integer pageSize) {
        // 构建查询条件
        LambdaQueryWrapper<WithdrawalApplication> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(WithdrawalApplication::getUserId, userId);

        // 申请状态
        if (StringUtils.isNotBlank(status) && !status.equals("all")) {
            queryWrapper.eq(WithdrawalApplication::getStatus, status);
        }

        // 排序
        queryWrapper.orderByDesc(WithdrawalApplication::getCreatedAt);

        // 分页查询
        IPage<WithdrawalApplication> withdrawalPage = withdrawalApplicationMapper.selectPage(
                new Page<>(page, pageSize),
                queryWrapper);

        // 转换为VO
        List<WithdrawalVO> withdrawalVOs = new ArrayList<>();
        for (WithdrawalApplication withdrawal : withdrawalPage.getRecords()) {
            WithdrawalVO vo = new WithdrawalVO();
            BeanUtils.copyProperties(withdrawal, vo);
            withdrawalVOs.add(vo);
        }

        // 构建分页结果
        return PageResult.of(withdrawalVOs, withdrawalPage.getTotal(), page, pageSize);
    }
}